using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Microsoft.Xna.Framework;
using Xfinity.Entities;

namespace Xfinity.Weapons
{
    /// <summary>
    /// A structure to model the movement of a projectile.
    /// </summary>
    public struct Projectile
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="Projectile"/> class.
        /// </summary>
        /// <param name="initialPosition">The initial position.</param>
        /// <param name="initialVelocity">The initial velocity.</param>
        /// <param name="initialAcceleration">The initial acceleration.</param>
        /// <param name="projectileProperties">The projectile properties.</param>
        /// <param name="weaponManager">The weapon manager.</param>
        public Projectile(Vector3 initialPosition, Vector3 initialVelocity, Vector3 initialAcceleration, ProjectileProperties projectileProperties, WeaponManager weaponManager)
        {
            position = initialPosition;
            Velocity = initialVelocity;
            Acceleration = initialAcceleration;
            oldPosition = position;
            this.projectileProperties = projectileProperties;
            weaponManager.Add(ref this);
        }
        private ProjectileProperties projectileProperties;
        private Vector3 position;
        private Vector3 oldPosition;
        /// <summary>
        /// Gets or sets the position.
        /// </summary>
        /// <value>The position.</value>
        public Vector3 Position
        {
            get { return position; }
            set { oldPosition = position; position = value; }
        }
        /// <summary>
        /// The velocity of the projectile.
        /// </summary>
        public Vector3 Velocity;

        /// <summary>
        /// Updates the position.
        /// </summary>
        /// <param name="seconds">The seconds.</param>
        public void Update(ref float seconds)
        {
            Velocity += Acceleration * seconds;
            position += Velocity * seconds;
        }
        private static List<GravitationalAttractor> attractors = new List<GravitationalAttractor>();

        /// <summary>
        /// Gets the attractors.
        /// </summary>
        /// <value>The attractors.</value>
        [SuppressMessage("Microsoft.Design", "CA1002:DoNotExposeGenericLists")]
        public static List<GravitationalAttractor> Attractors
        {
            get { return attractors; }
        }

        /// <summary>
        /// The acceleration of the projectile.
        /// </summary>
        public Vector3 Acceleration;


        /// <summary>
        /// Tests for a hit.
        /// </summary>
        /// <param name="objectToTest">The object to test.</param>
        /// <returns></returns>
        public bool TestForHit(BoundingBox objectToTest)
        {
            float? hit = objectToTest.Intersects(new Ray(position, oldPosition - position));
            if (hit != null && hit > 0 && hit < 1)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        /// <summary>
        /// Tests for a hit.
        /// </summary>
        /// <param name="objectToTest">The object to test.</param>
        /// <returns></returns>
        public bool TestForHit(BoundingSphere objectToTest)
        {
            float? hit = objectToTest.Intersects(new Ray(position, oldPosition - position));
            if (hit != null && hit > 0 && hit < 1)
            {
                return true;
            }
            
            else
            {
                return false;
            }
        }
        /// <summary>
        /// Tests for a hit.
        /// </summary>
        /// <param name="objectToTest">The object to test.</param>
        /// <returns></returns>
        public bool TestForHit(BoundingFrustum objectToTest)
        {
            float? hit = objectToTest.Intersects(new Ray(position, oldPosition - position));
            if (hit != null && hit > 0 && hit < 1)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    }
}